import * as THREE from "../../../modules/three/three.module.js";
import {PI2} from "./StaticMethods.js";

export default class SphericalUpZ {
  constructor( radius = 1, phi = 0, theta = 0 ) {
    return this.set(radius, phi, theta);
  }

  set( radius, phi, theta ) {
    this.radius = radius;
    this.phi = phi;  // polar angle
    this.theta = theta;  // azimuthal angle
    if (this.theta > Math.PI) {
      this.theta -= PI2
    } else if (this.theta < -Math.PI) {
      this.theta += PI2
    }
    return this;
  }
  copy( other ) {
    this.radius = other.radius;
    this.phi = other.phi;
    this.theta = other.theta;
    return this;
  }

  // restrict phi to be between EPS and PI-EPS
  makeSafe() {
    const EPS = 0.000001;
    this.phi = Math.max( EPS, Math.min( Math.PI - EPS, this.phi ) );
    return this;
  }
  setFromVector3( v ) {
    return this.setFromCartesianCoords( v.x, v.y, v.z );
  }

  setFromCartesianCoords( x, y, z ) {
    this.radius = Math.sqrt( x * x + y * y + z * z );
    if ( this.radius === 0 ) {
      this.theta = 0;
      this.phi = 0;
    } else {
      this.theta = Math.atan2( x, y );
      this.phi = Math.acos( THREE.MathUtils.clamp( z / this.radius, - 1, 1 ) );
    }
    if (this.theta > Math.PI) {
      this.theta -= PI2
    } else if (this.theta < -Math.PI) {
      this.theta += PI2
    }
    return this;
  }

  clone() {
    return new this.constructor().copy( this );
  }

  toArray() {
    return [this.radius, this.phi, this.theta]
  }

  toVector3(target) {
    if (!target) {
      target = new THREE.Vector3()
    }
    const {radius, phi, theta} = this
    const sinPhiRadius = Math.sin( phi ) * radius;

    target.x = sinPhiRadius * Math.sin( theta );
    target.z = Math.cos( phi ) * radius;
    target.y = sinPhiRadius * Math.cos( theta );

    return target;
  }
}
